/**
 * 
 */
package com.oauth.linkedin.server.service;

import java.util.EnumSet;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;

import org.gwtwidgets.server.spring.ServletUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.code.linkedinapi.client.LinkedInApiClient;
import com.google.code.linkedinapi.client.LinkedInApiClientFactory;
import com.google.code.linkedinapi.client.enumeration.ProfileField;
import com.google.code.linkedinapi.client.oauth.LinkedInAccessToken;
import com.google.code.linkedinapi.client.oauth.LinkedInOAuthService;
import com.google.code.linkedinapi.client.oauth.LinkedInOAuthServiceFactory;
import com.google.code.linkedinapi.client.oauth.LinkedInRequestToken;
import com.google.code.linkedinapi.schema.Connections;
import com.google.code.linkedinapi.schema.Network;
import com.google.code.linkedinapi.schema.Person;
import com.oauth.common.server.util.OAuthStringUtil;
import com.oauth.linkedin.client.beans.LinkedinUser;
import com.oauth.linkedin.server.conf.LinkedinInfoBean;
import com.oauth.linkedin.server.conf.LinkedinOAuthConfig;
import com.oauth.linkedin.server.util.LinkedinUtil;
import com.oauth.service.application.ApplicationService;
import com.oauth.service.generic.beans.OAuthServiceBean;
import com.oauth.service.global.beans.Birthday;
import com.oauth.service.global.beans.OAuthAccessToken;
import com.oauth.service.global.beans.OAuthRequestToken;

/**
 * @author asanthan
 * 
 */
@Service
public class LinkedinServiceImpl implements LinkedinService {

	private LinkedInOAuthService linkedInOauthService;
	private LinkedInApiClientFactory factory;

	@Autowired
	private ApplicationService applicationService;

	@Autowired
	private LinkedinOAuthConfig mOAuthConfigBean;

	@Autowired
	private LinkedinInfoBean infoBean;

	@PostConstruct
	public void initialize() {
		linkedInOauthService = LinkedInOAuthServiceFactory.getInstance()
				.createLinkedInOAuthService(mOAuthConfigBean.getConsumerKey(),
						mOAuthConfigBean.getConsumerSecret());
		factory = LinkedInApiClientFactory.newInstance(mOAuthConfigBean.getConsumerKey(),
				mOAuthConfigBean.getConsumerSecret());
	}

	private LinkedInApiClient getLinkedInClient(Long pMemberId) throws Exception {
		OAuthAccessToken accessToken = getAccessTokenFromDB(pMemberId);
		LinkedInAccessToken linkedinToken = new LinkedInAccessToken(accessToken.getToken(),
				accessToken.getTokenSecret());
		LinkedInApiClient client = factory.createLinkedInApiClient(linkedinToken);
		return client;
	}

	private Person getProfile(Long pMemberId, EnumSet<ProfileField> pFieldSet) throws Exception {
		return getLinkedInClient(pMemberId).getProfileForCurrentUser(pFieldSet);
	}

	private OAuthAccessToken getAccessTokenFromDB(Long pMemberId) throws Exception {
		OAuthServiceBean token = null;
		token = applicationService.getToken(pMemberId, infoBean.getKey());
		if (token != null) {
			return new OAuthAccessToken(token.getAccessToken(), token.getAccessTokenSecret());
		}
		return null;
	}

	@Override
	public OAuthAccessToken getAccessTokenFromRequestToken(OAuthRequestToken pRequestToken)
			throws Exception {
		HttpServletRequest request = ServletUtils.getRequest();
		String verifier = request.getParameter("oauth_verifier");
		if (OAuthStringUtil.isBlank(verifier)) {
			throw new Exception("Verifier not found");
		}

		LinkedInRequestToken requestToken = new LinkedInRequestToken(pRequestToken.getToken(),
				pRequestToken.getTokenSecret());
		LinkedInAccessToken accessToken = linkedInOauthService.getOAuthAccessToken(requestToken,
				verifier);

		// Get access token .
		return new OAuthAccessToken(accessToken.getToken(), accessToken.getTokenSecret());
	}

	@Override
	public OAuthRequestToken getRequestToken() throws Exception {
		LinkedInRequestToken requestToken = linkedInOauthService
				.getOAuthRequestToken(mOAuthConfigBean.getCallbackUrl());
		return new OAuthRequestToken(requestToken.getToken(), requestToken.getTokenSecret(),
				requestToken.getAuthorizationUrl());
	}

	@Override
	public List<LinkedinUser> getConnections(Long pMemberId) throws Exception {
		Connections connections = getLinkedInClient(pMemberId).getConnectionsForCurrentUser();
		return LinkedinUtil.getUsers(connections);
	}

	@Override
	public List<Birthday> getUpcomingBirthdays(Long pMemberId, int pBirthdayInterval)
			throws Exception {
		Connections connections = getLinkedInClient(pMemberId).getConnectionsForCurrentUser(
				EnumSet.of(ProfileField.DATE_OF_BIRTH, ProfileField.FIRST_NAME,
						ProfileField.LAST_NAME, ProfileField.ID, ProfileField.PICTURE_URL,
						ProfileField.PUBLIC_PROFILE_URL));
		return LinkedinUtil.getBirthdays(connections, pBirthdayInterval);

	}

	@Override
	public List<LinkedinUser> getMessages(Long pMemberId) throws Exception {
		// getLinkedInClient(pMemberId).getp
		return null;
	}

	@Override
	public List<LinkedinUser> getUpdates(Long pMemberId) throws Exception {
		Network network = getLinkedInClient(pMemberId).getNetworkUpdates(LinkedinUtil.updatesSet);
		return LinkedinUtil.getUpdates(network.getUpdates());

	}

	@Override
	public LinkedinUser getLinkedinUser(Long pMemberId) throws Exception {
		Person profile = getProfile(pMemberId, EnumSet.of(ProfileField.FIRST_NAME,
				ProfileField.LAST_NAME, ProfileField.HEADLINE, ProfileField.PICTURE_URL,
				ProfileField.CURRENT_STATUS));
		return LinkedinUtil.getUser(profile);
	}

	@Override
	public void updateStatus(String pText, Long pMemberId) throws Exception {
		System.out.println("Updating..." + pText);
		getLinkedInClient(pMemberId).postNetworkUpdate(pText);
	}
}
